﻿
#include <iostream>
#include "zyEditBox.h"
#include <wchar.h>
DarkMoonUI::zyEditBox::zyEditBox()
{
	SetMember(L"this", (LONG_PTR)this);
	m_obj->setWndProc(zyEditBox_WndProc);
	m_obj->setChildWndProc(zyEditBox_ChildWndProc);
	m_obj->setDestroy(zyEditBox_Destroy);
}
DarkMoonUI::zyEditBox::~zyEditBox()
{

}
void DarkMoonUI::zyEditBox::OnNCDestroy() {
	RECT* m_rectNCTop = (RECT*)GetMember(L"rectNCTop");
	RECT* m_rectNCBottom = (RECT*)GetMember(L"rectNCBottom");
	if (m_rectNCTop != nullptr)
		delete (m_rectNCTop);
	if (m_rectNCBottom != nullptr)
		delete (m_rectNCBottom);
	SetMember(L"rectNCTop", 0);
	SetMember(L"rectNCBottom", 0);
}
void WINAPI DarkMoonUI::zyEditBox::zyEditBox_Destroy(zyObject* obj)
{
	zyEditBox* zye = (zyEditBox*)obj->getPtrData(L"this");
	zye->OnNCDestroy();
	zyCommandCtrol::zyCommand_Destroy(obj);
}
LRESULT WINAPI DarkMoonUI::zyEditBox::zyEditBox_WndProc(zyObject* obj, HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL* bHandled)
{
	//std::cout << "zyEditBox_WndProc=uMsg: "<< uMsg << std::endl;
	switch (uMsg)
	{
	case WM_KEYDOWN: {
		if (wParam == VK_TAB) {
			LONG_PTR zyStyle = (LONG_PTR)obj->getPtrData(L"zyStyle");
			if ((GetWindowLong(hWnd, GWL_STYLE) & ES_WANTRETURN) == 0 && (zyStyle & ZY窗口风格_需要TAB键) == 0) {
				int bPrevious = (GetAsyncKeyState(VK_SHIFT) | 32768) != 0;
				HWND focus = GetNextDlgTabItem(GetAncestor(hWnd, GA_ROOT), hWnd, bPrevious);
				if (focus != 0) {
					SetFocus(focus);
					*bHandled = true;
					return 0;
				}
			}
		}
		else if (wParam == VK_RETURN) {
			LONG_PTR zyStyle = (LONG_PTR)obj->getPtrData(L"zyStyle");
			if ((GetWindowLong(hWnd, GWL_STYLE) & ES_WANTRETURN) == 0 && (zyStyle & ZY窗口风格_需要回车键) == 0) {
				HWND hWndTop = GetParent(hWnd);
				SendMessage(hWndTop, WM_COMMAND, MAKEWPARAM(IDOK, 0), 0);
				*bHandled = true;
				return 0;
			}
		}
	}
				   break;
	case WM_NCCALCSIZE: {
		if (obj->hasPtrData(L"vCenter")) {
			//获取字体高度
			HFONT hFont = (HFONT)SendMessage(hWnd, WM_GETFONT, 0, 0);
			HDC hdc = GetDC(hWnd);
			if (hFont == 0)
				hFont = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
			HGDIOBJ oldFont = SelectObject(hdc, hFont);
			RECT rectText = { 0 };
			DrawText(hdc, L"ky", 2, &rectText, DT_CALCRECT | DT_LEFT);
			int uiVClientHeight = rectText.bottom - rectText.top;
			SelectObject(hdc, oldFont);
			ReleaseDC(hWnd, hdc);
			RECT rectWnd = { 0 };
			GetWindowRect(hWnd, &rectWnd);// 获取居中矩形
			int uiCX = 0;
			int uiCY = 0;
			if (obj->hasPtrData(L"uiCX")) {
				uiCX = (int)(UINT_PTR)obj->getPtrData(L"uiCX");
				uiCY = (int)(UINT_PTR)obj->getPtrData(L"uiCY");
			}
			else {
				RECT rectClient = { 0 };
				GetClientRect(hWnd, &rectClient);
				POINT pt = { rectClient.left,rectClient.top };
				ClientToScreen(hWnd, &pt);

				POINT topLeft = { rectClient.left, rectClient.top };
				POINT topRight = { rectClient.right, rectClient.top };
				POINT bottomLeft = { rectClient.left, rectClient.bottom };
				POINT bottomRight = { rectClient.right, rectClient.bottom };

				ClientToScreen(hWnd, &topLeft);
				ClientToScreen(hWnd, &topRight);
				ClientToScreen(hWnd, &bottomLeft);
				ClientToScreen(hWnd, &bottomRight);
				// 更新RECT的四个点  
				rectClient.left = topLeft.x;
				rectClient.top = topLeft.y;
				rectClient.right = bottomRight.x;
				rectClient.bottom = bottomRight.y;

				uiCX = (rectWnd.right - rectWnd.left - (rectClient.right - rectClient.left)) / 2;
				uiCY = (rectWnd.bottom - rectWnd.top - (rectClient.bottom - rectClient.top)) / 2;
				obj->setPtrData(L"uiCX", (void*)(UINT_PTR)uiCX);
				obj->setPtrData(L"uiCY", (void*)(UINT_PTR)uiCY);
			}
			int uiCenterOffset = (rectWnd.bottom - rectWnd.top - uiVClientHeight) / 2;

			// 保存被修改后的非客户区(上下空白区域)
			OffsetRect(&rectWnd, -rectWnd.left, -rectWnd.top);
			//rectWnd = {-rectWnd.left,  -rectWnd.top , rectWnd.right, rectWnd.bottom};
			RECT* m_rectNCTop = nullptr;
			RECT* m_rectNCBottom = nullptr;
			int offsetRight = (int)(INT_PTR)obj->getPtrData(L"offsetRight");
			if (obj->hasPtrData(L"rectNCTop") == false) {
				m_rectNCTop = new RECT;
				obj->setPtrData(L"rectNCTop", (void*)m_rectNCTop);
			}
			else {
				m_rectNCTop = (RECT*)obj->getPtrData(L"rectNCTop");
			}
			if (obj->hasPtrData(L"rectNCBottom") == false) {
				m_rectNCBottom = new RECT;
				obj->setPtrData(L"rectNCBottom", (void*)m_rectNCBottom);
			}
			else {
				m_rectNCBottom = (RECT*)obj->getPtrData(L"rectNCBottom");
			}
			if (m_rectNCTop != nullptr && rectWnd.bottom > 0 && rectWnd.right > 0) {
				RtlMoveMemory(m_rectNCTop, &rectWnd, sizeof(RECT));
				m_rectNCTop->left += uiCX;
				m_rectNCTop->top += uiCY;
				m_rectNCTop->right -= offsetRight;//默认18是当关联了调节器的时候，就不会导致当编辑框获取光标的时候把调节器给填充了一部分。会看着不正常不好看
				m_rectNCTop->bottom -= uiCenterOffset + uiVClientHeight;
			}
			if (m_rectNCBottom != nullptr && rectWnd.bottom > 0 && rectWnd.right > 0) {
				RtlMoveMemory(m_rectNCBottom, &rectWnd, sizeof(RECT));
				m_rectNCBottom->left += uiCX;
				m_rectNCBottom->top += uiCenterOffset + uiVClientHeight;
				m_rectNCBottom->right -= offsetRight;//默认18是当关联了调节器的时候，就不会导致当编辑框获取光标的时候把调节器给填充了一部分。会看着不正常不好看
				m_rectNCBottom->bottom -= uiCY;
			}		// 修改非客户区
			NCCALCSIZE_PARAMS* p = (NCCALCSIZE_PARAMS*)lParam;
			p->rgrc[0].left += uiCX;
			p->rgrc[0].top += uiCenterOffset;
			p->rgrc[0].right -= uiCY;
			p->rgrc[0].bottom -= uiCenterOffset;
			//memcpy((void*)lParam, p, sizeof(NCCALCSIZE_PARAMS)); 
			//std::cout << "zyEditBox_WndProc=left: " << p->rgrc[0].left << " top: " << p->rgrc[0].top << " top: " << p->rgrc[0].right << " top: " << p->rgrc[0].bottom << std::endl;
			*bHandled = true;
			return 0;
		}
	}
		break;
	case WM_NCPAINT: {
		if (obj->hasPtrData(L"vCenter")) {
			RECT* m_rectNCTop = (RECT*)obj->getPtrData(L"rectNCTop");
			RECT* m_rectNCBottom = (RECT*)obj->getPtrData(L"rectNCBottom");
			if (m_rectNCTop != 0 && m_rectNCBottom != 0) {
				DefWindowProc(hWnd, uMsg, wParam, lParam);
				HDC hdc = GetWindowDC(hWnd);
				HBRUSH hBrush = CreateSolidBrush(GetSysColor(COLOR_WINDOW));
				FillRect(hdc, m_rectNCTop, hBrush);
				FillRect(hdc, m_rectNCBottom, hBrush);
				DeleteObject(hBrush);
				ReleaseDC(hWnd, hdc);
			}
		}
	}
	break;
	case WM_NCDESTROY: {
		zyEditBox* zyE = (zyEditBox*)obj->getPtrData(L"this");
		zyE->OnNCDestroy();
	}
	break;
	}
	return zyCommandCtrol::zyCommand_WndProc(obj, hWnd, uMsg, wParam, lParam, bHandled);
}

LRESULT WINAPI DarkMoonUI::zyEditBox::zyEditBox_ChildWndProc(zyObject* obj, HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, BOOL* bHandle)
{
	if (message == WM_COMMAND)
	{
		short id = LOWORD(wParam);
		short code = HIWORD(wParam);
		if (code == EN_CHANGE) {
			TRegEvent* evtPtr = obj->getRegEvent(L"OnTextChange");
			if (evtPtr != nullptr) {
				evtPtr->handler<LRESULT>(lParam, id);
			}
		}
	}
	return zyCommandCtrol::zyCommand_ChildWndProc(obj, hWnd, message, wParam, lParam, bHandle);
}

BOOL DarkMoonUI::zyEditBox::创建(HWND 参数_父窗口, const std::wstring& 参数_标题, POINT 参数_位置, POINT 参数_尺寸, int 参数_ID, int 参数_窗口风格, int 参数_扩展风格)
{
	if (参数_窗口风格 == 0)
		参数_窗口风格 = ES_AUTOHSCROLL | WS_TABSTOP;
	if (参数_扩展风格 == 0)
		参数_扩展风格 = WS_EX_CLIENTEDGE;
	if (参数_ID == NULL)
		参数_ID = 黑月默认ID();
	bool ret = _CreateCtrol(参数_父窗口, 参数_标题, 参数_位置, 参数_尺寸, 参数_ID, 参数_窗口风格, 参数_扩展风格, L"Edit");
	if ((GetStyle() & ES_WANTRETURN) != 0)
		置ZY窗口风格(ZY窗口风格_需要回车键);
	return ret;
}

BOOL DarkMoonUI::zyEditBox::创建(zyWindow& 参数_父窗口, const std::wstring& 参数_标题, POINT 参数_位置, POINT 参数_尺寸, int 参数_ID, int 参数_窗口风格, int 参数_扩展风格)
{
	if (参数_窗口风格 == 0)
		参数_窗口风格 = ES_AUTOHSCROLL | WS_TABSTOP;
	if (参数_扩展风格 == 0)
		参数_扩展风格 = WS_EX_CLIENTEDGE;
	if (参数_ID == NULL)
		参数_ID = 黑月默认ID();
	bool ret = _CreateCtrol((HWND)参数_父窗口.GetMember(L"hWnd"), 参数_标题, 参数_位置, 参数_尺寸, 参数_ID, 参数_窗口风格, 参数_扩展风格, L"Edit");
	if ((GetStyle() & ES_WANTRETURN) != 0)
		置ZY窗口风格(ZY窗口风格_需要回车键);
	return ret;
}

void DarkMoonUI::zyEditBox::OnTextChange(TRegEvent* 参数_事件指针) {
	SetRegEvent(L"OnTextChange", 参数_事件指针);
}
void DarkMoonUI::zyEditBox::取光标所在行列(int& 参数_行号, int& 参数_列号) {
	int start = 0;
	sendMsg(EM_GETSEL, (WPARAM)&start, 0);
	参数_行号 = (int)sendMsg(EM_LINEFROMCHAR, start, 0);
	参数_列号 = start - (int)sendMsg(EM_LINEINDEX, 参数_行号, 0);
}
int DarkMoonUI::zyEditBox::取坐标字符(int 参数_水平坐标, int 参数_垂直坐标) {
	int ret = (int)sendMsg(EM_CHARFROMPOS, 0, MAKELPARAM(参数_水平坐标, 参数_垂直坐标));
	return LOWORD(ret);
}
POINT DarkMoonUI::zyEditBox::取字符坐标(int 参数_字符位置) {
	int ret = (int)sendMsg(EM_POSFROMCHAR, 参数_字符位置, 0);
	POINT pt = { LOWORD(ret),HIWORD(ret) };
	return pt;
}
std::wstring DarkMoonUI::zyEditBox::取行文本(int 参数_行号) {
	int 局部_起始位置 = (int)sendMsg(EM_LINEINDEX, 参数_行号, 0);
	int 局部_长度 = (int)sendMsg(EM_LINELENGTH, 局部_起始位置, 0);
	if (局部_长度 == 0)
		return L"";
	std::wstring txt;
	txt.reserve(局部_长度 + 1);
	sendMsg(EM_GETLINE, 参数_行号, (LPARAM)txt.c_str());
	return txt;
}
BOOL DarkMoonUI::zyEditBox::滚动到光标() {
	int start = 0;
	sendMsg(EM_GETSEL, (WPARAM)&start, 0);
	int line = (int)sendMsg(EM_LINEFROMCHAR, start, 0);
	int index = start - (int)sendMsg(EM_LINEINDEX, line, 0);
	int visibleLine = (int)sendMsg(EM_GETFIRSTVISIBLELINE, 0, 0);
	return sendMsg(EM_LINESCROLL, line, line - visibleLine) != 0;
}
BOOL DarkMoonUI::zyEditBox::滚动(int 参数_水平字符数, int 参数_行数) {
	return sendMsg(EM_LINESCROLL, 参数_水平字符数, 参数_行数) != 0;
}
void DarkMoonUI::zyEditBox::移动(int 参数_左边, int 参数_顶边, int 参数_宽度, int 参数_高度, BOOL 参数_是否立即重画) {//MoveWindow
	RECT 局部_rect = { 0 };
	POINT 局部_pt = { 0 };
	HWND hwnd = 取窗口句柄();
	if (hwnd != 0) {
		GetWindowRect(hwnd, &局部_rect);
		局部_pt.x = 局部_rect.left;
		局部_pt.y = 局部_rect.top;
		ScreenToClient(GetParent(hwnd), &局部_pt);
		if (参数_左边 == 0)
			参数_左边 = 局部_pt.x;
		if (参数_顶边 == 0)
			参数_顶边 = 局部_pt.y;
		if (参数_宽度 == 0)
			参数_宽度 = 局部_rect.right - 局部_rect.left;
		if (参数_高度 == 0)
			参数_高度 = 局部_rect.bottom - 局部_rect.top;
		MoveWindow(hwnd, 参数_左边, 参数_顶边, 参数_宽度, 参数_高度, 参数_是否立即重画);
		if (参数_是否立即重画)
			SetWindowPos(hwnd, 0, 0, 0, 0, 0, SWP_NOOWNERZORDER | SWP_NOSIZE | SWP_NOMOVE | SWP_FRAMECHANGED);
	}
}
BOOL DarkMoonUI::zyEditBox::垂直居中(BOOL 参数_垂直居中,int offsetRight) {
	SetMember(L"vCenter", 参数_垂直居中);
	SetMember(L"offsetRight", offsetRight);
	HWND hwnd = 取窗口句柄();
	if (IsWindow(hwnd))
		SetWindowPos(hwnd, 0, 0, 0, 0, 0, SWP_NOOWNERZORDER | SWP_NOSIZE | SWP_NOMOVE | SWP_FRAMECHANGED | SWP_NOZORDER);
	return GetMember(L"vCenter") != 0;
}
void DarkMoonUI::zyEditBox::置矩形(RECT 参数_矩形) {
	sendMsg(EM_SETRECT, 0, (LPARAM)&参数_矩形);
}
RECT DarkMoonUI::zyEditBox::取矩形() {
	RECT rc = { 0 };
	sendMsg(EM_GETRECT, 0, (LPARAM)&rc);
	return rc;
}
int DarkMoonUI::zyEditBox::最大长度(int 参数_最大长度) {
	if (参数_最大长度 == 0)
		return (int)sendMsg(EM_GETLIMITTEXT, 0, 0);
	return (int)sendMsg(EM_GETLIMITTEXT, 参数_最大长度, 0);
}
void DarkMoonUI::zyEditBox::替换文本(const std::wstring& 参数_文本) {
	sendMsg(EM_REPLACESEL, 1, (LPARAM)参数_文本.c_str());
}
void DarkMoonUI::zyEditBox::添加文本(const std::wstring& 参数_文本) {
	sendMsg(EM_SETSEL, -2, -1);
	sendMsg(EM_REPLACESEL, 1, (LPARAM)参数_文本.c_str());
}
std::wstring DarkMoonUI::zyEditBox::内容(const std::wstring& 参数_内容) {//参数留空为取，否则为置。
	if (!参数_内容.empty())
		置文本(参数_内容);
	return 取文本();
}
void DarkMoonUI::zyEditBox::取被选择区(int& 参数_起始位置, int& 参数_结束位置) {
	sendMsg(EM_GETSEL, 参数_起始位置, 参数_结束位置);
}
void DarkMoonUI::zyEditBox::置被选择文本(int 参数_起始位置, int 参数_结束位置) {//使编辑框的文本处于被选择状态。
	sendMsg(EM_SETSEL, 参数_起始位置, 参数_结束位置);
}
BOOL DarkMoonUI::zyEditBox::置只读属性(BOOL 参数_属性值) { return sendMsg(EM_SETREADONLY, 参数_属性值, 0) != 0; }
void DarkMoonUI::zyEditBox::置密码遮盖符(const wchar_t* 参数_遮盖符) {
	if (参数_遮盖符 == nullptr) {
		// 处理空指针情况，可以选择设置默认遮盖符或抛出异常
		sendMsg(EM_SETPASSWORDCHAR, (WPARAM)'\0', 0);
		return;
	}

	wchar_t 遮盖符 = *参数_遮盖符;  // 获取第一个字符
	if (sendMsg(EM_SETPASSWORDCHAR, (WPARAM)遮盖符, 0) == 0) {
		// 处理 sendMsg 调用失败的情况
		// 可以选择记录日志或抛出异常
		// 例如：std::cerr << "Failed to set password char" << std::endl;
	}
}
std::wstring DarkMoonUI::zyEditBox::取密码遮盖符() {
	wchar_t passwordChar = static_cast<wchar_t>(sendMsg(EM_GETPASSWORDCHAR, 0, 0));
	if (passwordChar == 0) {
		// 处理异常情况，例如返回默认值或抛出异常
		return L""; // 或者抛出异常
	}
	return std::wstring(1, passwordChar);
}
int DarkMoonUI::zyEditBox::取可见第一行() { return (int)sendMsg(EM_GETFIRSTVISIBLELINE, 0, 0); }
void DarkMoonUI::zyEditBox::置内容改变标志(BOOL 参数_是否改变) { sendMsg(EM_SETMODIFY, 参数_是否改变, 0); }
BOOL DarkMoonUI::zyEditBox::内容是否改变() { return sendMsg(EM_GETMODIFY, 0, 0) != 0; }
int DarkMoonUI::zyEditBox::删除() { return (int)sendMsg(WM_CLEAR, 0, 0); }
int DarkMoonUI::zyEditBox::粘贴() { return (int)sendMsg(WM_PASTE, 0, 0); }
int DarkMoonUI::zyEditBox::复制() { return (int)sendMsg(WM_COPY, 0, 0); }
int DarkMoonUI::zyEditBox::剪切() { return (int)sendMsg(WM_CUT, 0, 0); }
int DarkMoonUI::zyEditBox::清除撤销缓冲区() { return (int)sendMsg(EM_EMPTYUNDOBUFFER, 0, 0); }
void DarkMoonUI::zyEditBox::撤销() { sendMsg(EM_UNDO, 0, 0); }
BOOL DarkMoonUI::zyEditBox::可否撤销() { return sendMsg(EM_CANUNDO, 0, 0) != 0; }
int DarkMoonUI::zyEditBox::取行数() { return (int)sendMsg(EM_GETLINECOUNT, 0, 0); }
int DarkMoonUI::zyEditBox::取行号(int 参数_字符位置) { return (int)sendMsg(EM_LINEFROMCHAR, 参数_字符位置, 0); }
int DarkMoonUI::zyEditBox::取行首位置(int 参数_行号) { return (int)sendMsg(EM_LINEINDEX, 参数_行号, 0); }
int DarkMoonUI::zyEditBox::取行文本长度(int 参数_行号) { return (int)sendMsg(EM_LINELENGTH, sendMsg(EM_LINEINDEX, 参数_行号, 0), 0); }